package com.xingchi.tornado.security.config;

import com.xingchi.tornado.core.constants.HeaderNames;
import org.apache.commons.lang3.StringUtils;
import org.springframework.session.web.http.CookieHttpSessionIdResolver;
import org.springframework.session.web.http.CookieSerializer;
import org.springframework.session.web.http.DefaultCookieSerializer;
import org.springframework.session.web.http.HttpSessionIdResolver;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

public class CompositeSessionIdResolver implements HttpSessionIdResolver {

    private final CookieHttpSessionIdResolver cookieResolver = new CookieHttpSessionIdResolver();

    public CompositeSessionIdResolver(CookieSerializer cookieSerializer) {
        cookieResolver.setCookieSerializer(cookieSerializer);
    }

    @Override
    public List<String> resolveSessionIds(HttpServletRequest request) {
        List<String> sessionIds = new ArrayList<>();

        // 获取优先级 请求参数中的token > 请求参数中的sessionId > 请求参数头中的Authorization > 请求参数头中的X-Auth-Token
        String sessionId = this.getSessionId(request);
        if (StringUtils.isNotBlank(sessionId)) {
            sessionIds.add(sessionId);
        }
        // 3. 最后从 Cookie 获取（浏览器环境）
        List<String> cookieSessionIds = cookieResolver.resolveSessionIds(request);
        sessionIds.addAll(cookieSessionIds);
        return sessionIds;
    }

    @Override
    public void setSessionId(HttpServletRequest request, HttpServletResponse response, String sessionId) {
        // 1. 写入 Cookie（浏览器环境）
        cookieResolver.setSessionId(request, response, sessionId);

        // 2. 写入 Header（APP/小程序环境）
        response.setHeader(HeaderNames.X_AUTH_TOKEN, sessionId);
    }

    @Override
    public void expireSession(HttpServletRequest request, HttpServletResponse response) {
        // 同时清理两种来源
        cookieResolver.expireSession(request, response);
        response.setHeader(HeaderNames.X_AUTH_TOKEN, "");
    }

    // 配置 Cookie 的 SameSite 策略
    public void setCookieSameSite(String sameSite) {
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        cookieSerializer.setSameSite(sameSite);
        cookieResolver.setCookieSerializer(cookieSerializer);
    }

    public String getSessionId(HttpServletRequest request) {

        String sessionId = request.getParameter("token");
        if (StringUtils.isNotBlank(sessionId)) {
            return sessionId;
        }

        String _sessionId = request.getParameter("sessionId");
        if (StringUtils.isNotBlank(_sessionId)) {
            return _sessionId;
        }

        String authorization = request.getHeader("Authorization");
        if (StringUtils.isNotBlank(authorization) && authorization.startsWith("Bearer ")) {
            return authorization.replace("Bearer ", "");
        }

        return request.getHeader(HeaderNames.X_AUTH_TOKEN);
    }
}
